<template>
  <div class="playlist-container">
    <nav-bar :title="title" :title2="Disc.name" fixed left-arrow :show-title2="showName" :background="NavBarBgColor" :color="NavBarColor" />

    <div class="bg-img" :style="{backgroundImage: `url(${Disc.imgUrl})`}" ref="bgImg">
      <img class="filter" v-if="Type!==3" v-lazy="Disc.imgUrl">
      <div class="mask" />
    </div>

    <div class="music-list" :style="ScrollStyle" ref="scroll">
      <div class="content">
        <component :is="component"
                   :height="BgImgHeight"
                   :bg-img="Disc.imgUrl"
                   :Data.sync="Data"
                   @comment="commentPlayList"
                   @share="sharePlayList"
        />
        <ul class="songs-list" :style="{minHeight}">
          <SongItem v-for="(item, index) in List"
                    component-type="li"
                    :key="item.id"
                    :index="index+1"
                    :data="item"
                    :is-rank="isRank"
                    @select="selectSong(item)"
                    @open="openOperation(item)"
          />

          <li v-if="Loading" class="Loading">正在载入歌单数据...</li>
          <li v-else class="pullUp-tips">
            <div v-if="!isPullUpLoad" class="before-trigger" v-text="error?'下拉加载更多':'加载错误，请重试！'" />
            <div v-else-if="more" class="after-trigger">正在加载歌曲数据...</div>
            <div v-else-if="Type !== 3" class="no-more">没有歌曲了~</div>
          </li>

        </ul>
      </div>
    </div>

  </div>
</template>

<script>
import { debounce } from 'common/js/utils'
import { PlayListType } from 'common/js/constant'
import { GetPlayListDetail } from 'api/playlist'
import { GetSongDetailsAsync } from 'api/song'
import { GetArtistsAsync } from 'api/singer'
import { createSong } from 'common/js/Song'
import PlayList from 'common/js/playList'
import Singer from 'common/js/singer'
import SongItem from 'components/SongItem/SongItem'
import loading from 'components/loading/loading'
import Type1 from './components/type1'
import Type3 from './components/type3'
import BScroll from '@better-scroll/core'
import PullUp from '@better-scroll/pull-up'
BScroll.use(PullUp)

export default {
  name: 'play-list',
  data () {
    return {
      Type: 0,
      Data: {},
      PlayerHeight: 60,
      /*  滚动条 分页加载  */
      Scroll: null,
      isPullUpLoad: false,
      page: 0,
      pageSize: 100,
      error: false,
      more: true,

      Ids: [],
      List: [],
      showName: false,
      Loading: false,
      BgImgHeight: 0,
      ScrollHeight: 0,
      NavBarBgColor: 'transparent',
      NavBarColor: 'white'
    }
  },
  created () {
    this.Type = this.Disc.type
  },
  mounted () {
    //  计算歌单背景图高度
    this.BgImgHeight = this.$refs.bgImg.clientHeight
    this.ScrollHeight = this.$refs.scroll.clientHeight
    setTimeout(() => this._initScroll(), 20)
  },
  activated () {
    this.refresh()
  },
  methods: {
    _initScroll () {
      if (!this.$refs.scroll) return
      this.Scroll = new BScroll(this.$refs.scroll, {
        probeType: 3,
        click: true,
        scrollY: true,
        bounceTime: 400,
        pullUpLoad: true
      })
      this.Scroll.on('scroll', this.scroll)
      this.Scroll.on('pullingUp', this.pullUp)
      this.getPlayListData()
    },
    refresh: debounce(function () {
      this.Scroll && this.Scroll.refresh()
    }, 20),
    getPlayListData (state = false) {
      this.Loading = true
      switch (this.Type) {
        case 1: // playlist
          GetPlayListDetail(this.Disc.id).then(res => {
            this.Loading = false
            this.Ids = res.playlist.trackIds.map(i => i.id)
            const playlist = res.playlist
            this.Data = new PlayList({
              id: playlist.id,
              name: playlist.name,
              desc: playlist.description,
              trackCount: playlist.trackCount,
              playCount: playlist.playCount,
              commentCount: playlist.commentCount,
              shareCount: playlist.shareCount,
              subscribedCount: playlist.subscribedCount,
              subscribed: playlist.subscribed,
              imgUrl: playlist.coverImgUrl,
              tags: playlist.tags,
              userId: playlist.userId,
              userName: playlist.creator.nickname,
              userAvatar: playlist.creator.avatarUrl
            })
            this.Scroll && this.Scroll.autoPullUpLoad()
          }).catch(res => {
            console.log(res)
            this.Loading = false
            this.error = true
          })
          break
        case 3: //  singer
          GetArtistsAsync(this.Disc.id).then(res => {
            this.Loading = false
            if (res.msg) {
              this.$toast.fail(res.msg)
              this.error = true
            }
            this.Ids = res.hotSongs.map(item => item.id)
            const artist = res.artist
            this.Data = new Singer({
              id: artist.id,
              name: artist.name,
              avatar: artist.img1v1Url,
              cover: artist.picUrl,
              followed: artist.followed,
              musicCount: artist.musicSize,
              albumCount: artist.albumSize,
              mvCount: artist.mvSize,
              disc: artist.briefDesc
            })
            this.Scroll && this.Scroll.autoPullUpLoad()
          }).catch(err => {
            console.log(err)
            this.Loading = false
            this.error = true
          })
          break
      }
    },
    async pullUp () {
      this.isPullUpLoad = true
      this.error = false
      const Ids = this.Ids.slice(this.offset, this.offset + this.pageSize)
      try {
        let response = await Promise.all([GetSongDetailsAsync(Ids), this.$store.dispatch('GetSongUrlAsync2', Ids)])
        let [musicData, urls] = response
        let List = musicData.map(item => {
          const urlItem = urls.find(item2 => item2.id === item.id)
          return createSong(Object.assign({}, item, { url: urlItem.url }))
        })
        this.List = this.List.concat(List)
        this.page++

        if (this.Ids.length <= this.offset) {
          this.more = false
        } else {
          this.isPullUpLoad = false
          this.Scroll && this.Scroll.finishPullUp()
        }
      } catch (err) {
        console.log(err)
        this.error = true
        this.isPullUpLoad = false
        this.Scroll && this.Scroll.finishPullUp()
        this.$toast.fail('获取歌曲失败，请稍后尝试。')
      }
    },

    scroll (e) {
      if (e.y > -this.typesHeight) {
        this.NavBarBgColor = 'transparent'
        this.NavBarColor = 'white'
        this.showName = false
      } else {
        this.NavBarBgColor = ''
        this.NavBarColor = ''
        this.showName = true
      }
      if (e.y > 0) {
        this.$refs.bgImg.style.transform = `scale(${1 + Math.abs(e.y / this.BgImgHeight)})`
      }
    },
    selectSong (song) {
      this.$store.dispatch('player/setCurrentMusic', song)
      this.$store.dispatch('player/setPlayList', this.List)
      this.$router.push('player')
    },
    openOperation (song) {
      this.$emit('open', song)
    },
    sharePlayList () {
      this.$copy(`https://y.music.163.com/m/playlist?id=${this.Disc.id}`)
    },
    commentPlayList () {
      this.$router.push({
        path: '/comment',
        query: {
          type: 2,
          id: this.Disc.id
        }
      })
    }
  },
  watch: {
    List () {
      this.refresh()
    },
    showPlayer () {
      this.refresh()
    }
  },
  computed: {
    Disc () {
      return this.$store.state.Disc
    },
    isRank () {
      return !!this.Disc.isRank
    },
    title () {
      const Index = PlayListType.findIndex(item => item.type === this.Disc.type)
      return Index >= 0 ? PlayListType[Index].text : ''
    },
    component () {
      return this.Type ? 'type' + this.Type : false
    },
    typesHeight () {
      return this.BgImgHeight - this.$store.state.StatusBarHeight - this.$config.nav_bar_height
    },
    minHeight () {
      return this.ScrollHeight - this.typesHeight - 56 + 'px'
    },
    ScrollStyle () {
      return {
        top: this.$store.state.StatusBarHeight + 44 + 'px',
        bottom: this.showPlayer ? this.PlayerHeight + 'px' : 0
      }
    },
    showPlayer () {
      return !!this.$store.state.player.playList.length
    },

    offset () {
      return this.page * this.pageSize
    }
  },
  components: { loading, SongItem, Type1, Type3 }
}
</script>

<style scoped lang="less">
  @import "~common/style/variable.less";
  @import "~common/style/mixins.less";
  @bg-height: 70%;

  .playlist-container {
    width: 100%;
    height: 100%;
  }
  .bg-img {
    position: relative;
    width: 100%;
    height: 0;
    padding-top: @bg-height;
    transform-origin: top;
    background-size: cover;
    z-index: 0;
    background-color: @color-background;
    overflow: hidden;
    .filter {
      width: 100%;
      position: absolute;
      top: 0;
      left: 0;
      filter: blur(10px);
      background-size: cover;
    }
    .mask {
      position: absolute;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
      background: rgba(7,17,27,.4);
    }
  }
  .music-list {
    width: 100%;
    position: fixed;
    top: 0;
    bottom: 0;
    .songs-list {
      background: @color-background;
      .Loading, .pullUp-tips > div {
        padding: 20px;
        text-align: center;
        color: @color-text-d;
      }
    }
  }
</style>
